package com.yqs.aspect;

import com.yqs.abnormal.OutOfStackException;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author Ye QS
 * @version 0.1
 * @className LogAspectBean
 * @description 通知类
 * @date 2024/8/6 14:08
 * @since jdk11
 */
@Component
@Aspect
// 定义一个日志切面类，用于记录手机购买和销售操作的日志
public class LogAspectBean {

    // 在执行目标方法之前执行的方法，记录操作的日志信息
    @Before("p1()")
    public void before(JoinPoint jp) {
        // 获取方法参数
        Object[] args = jp.getArgs();
        // 获取方法名称
        String name = jp.getSignature().getName();
        // 如果是购买手机的方法，打印日志信息
        if ("buyPhone".equals(name)) {
            System.out.println("日志" + currTime() + "即将执行进货操作，数量为" + args[0]);
        }
        // 如果是销售手机的方法，打印日志信息
        if ("salPhone".equals(name)) {
            System.out.println("日志" + currTime() + "即将执行销售操作，数量为" + args[0]);
        }
    }

    // 在目标方法执行之后执行的方法，记录操作的日志信息
    @AfterReturning("p1()")
    public void afterReturning(JoinPoint jp) {
        String name = jp.getSignature().getName();
        if ("buyPhone".equals(name)) {
            System.out.println("日志：" + currTime() + "进货操作结束");
        }
        if ("salPhone".equals(name)) {
            System.out.println("日志：" + currTime() + "销售操作结束");
        }
    }

    // 在目标方法执行之后执行的方法，记录操作的日志信息，即使目标方法执行过程中出现异常也会执行
    @After("p1()")
    public void after(JoinPoint jp) {
        String name = jp.getSignature().getName();
        if ("buyPhone".equals(name)) {
            System.out.println("日志：" + currTime() + "进货操作结束,即使异常也要执行");
        }
        if ("salPhone".equals(name)) {
            System.out.println("日志：" + currTime() + "销售操作结束,即使异常也要执行");
        }
    }

    // 在目标方法执行过程中出现异常时执行的方法，记录异常信息
    @AfterThrowing(pointcut = "p1()", throwing = "e")
    public void afterThrowing(JoinPoint jp, OutOfStackException e) {
        String name = jp.getSignature().getName();
        System.out.println(currTime() + "方法执行的时候出现异常" + e.getMessage());
    }

    // 在目标方法执行前后执行的方法，记录方法执行的开始和结束时间，以及方法执行的耗时
    @Around("p1()")
    public Object aroundTest(ProceedingJoinPoint pjp) {
        String name = pjp.getSignature().getName();
        long start = System.currentTimeMillis();
        System.out.println(currTime() + name + "开始执行");
        try {
            return pjp.proceed();
        } catch (Throwable e) {
            throw new RuntimeException(e);
        } finally {
            long end = System.currentTimeMillis();
            System.out.println("执行完毕，耗时" + (end - start) + "毫秒");
        }
    }

    // 定义一个切点，匹配执行void类型、方法名以Phone结尾、参数类型为int的方法
    @Pointcut("execution(void *Phone(int))")
    public void p1() {

    }

    // 获取当前时间的字符串表示
    public String currTime() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        return sdf.format(new Date());
    }

}